import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Stack;

public class ASTToJava {

	Stack<BGDLTreeNode> stack;
	BGDLTreeNode root;
	String javaString;
	boolean isInitiated[];
	boolean isFirstCell;
	boolean currentFunction[];
	
	public ASTToJava(BGDLTreeNode root){
		this.root = root;
	}
	
	public String translate(){
		
		stack = new Stack<BGDLTreeNode>();
		if(root==null){
			System.out.println("Root is null: Error");
		}else{
			isInitiated = new boolean[4];
			currentFunction = new boolean[4];
			for(int i = 0;i<isInitiated.length;i++){
				isInitiated[i] = false;
				currentFunction[i] = false;
			}
			isFirstCell = true;
			javaString = "";
			//common beginning - no import allowed
			javaString += "public class BoardGame {\n\n";
					
			if(root.children.size()>0){
				
				//push all the children into stack
				for(int i = 0;i<this.root.children.size();i++){
					
					stack.push(this.root.children.get(i));
					
				}
				String errorFound = "";
				while(!stack.empty()){
					errorFound = determine();
					if(!errorFound.equals("")){
						//check error if inappropriate functions are in inappropriate 4 main functions
						//return true when error
						return errorFound;
					}
				}
				//main function
				javaString += "public static void main(String[] args){\n\n" +
				"Main game = new Main();\n"+
				"game.initial();\n";
				javaString += "game.go();\n" +
						"}\n\n";
				
			}
			
			//function for checking if the main 4 functions is generated
			javaString += "public static boolean isDefined(int index){\n"
				+ "if(index==0) return "+isInitiated[0]+";\n"
				+ "else if(index==1) return "+isInitiated[1]+";\n"
				+ "else if(index==2) return "+isInitiated[2]+";\n"
				+ "else if(index==3) return "+isInitiated[3]+";\n"
				+ "else return false;\n"
				+ "}\n";
			//check if any function is not generated, generate it
			if(!isInitiated[0]){
				//initializeBoard
				javaString += "public static void initializeBoard(Main game){\n"
					+ "}\n";
			}
			if(!isInitiated[1]){
				//GameOver
				javaString += "public static boolean GameOver(Main game){\n"
					+ "return false;\n"
					+ "}\n";
			}
			if(!isInitiated[2]){
				//Winner
				javaString += "public static Player[] Winner(Main game){\n"
					+ "return null;\n"
					+ "}\n";
			}
			if(!isInitiated[3]){
				//Cell
				javaString += "public static void InitializeCells(Main game, int x, int y){\n"
					+ "}\n";
			}
			//common ending - no self-created function allowed
			javaString += "}\n";
			
			//write Java file
			writeOutput();
			
		}
		
		return "";
		
	}
	
	private String determine() {
		
		BGDLTreeNode current = stack.pop();
		//find what value it is
		if(current.value.equals("function")){
			//function
			//can ignore the first child (every function has its own return type)
			//put children into stack
			stack.push(new BGDLTreeNode("CloseFunction"));
			stack.push(current.children.get(2)); // statement
			stack.push(current.children.get(1)); // name
			if(!stack.peek().value.equals("InitializeBoard")
					&&!stack.peek().value.equals("GameOver")
					&&!stack.peek().value.equals("Winner")
					&&!stack.peek().value.equals("InitializeCells")){
				System.out.println("Error: Function name "+stack.peek().value+" cannot be defined.");
			}
			
		}
		
		//<----------Functions-------->
		
		else if(current.value.equals("InitializeBoard")){
			//initial Board
			javaString += "public static void initializeBoard(Main game){\n";
			isInitiated[0] = true;
			currentFunction[0] = true;
			
		}else if(current.value.equals("GameOver")){
			
			//GameOver
			javaString += "public static boolean GameOver(Main game){\n";
			isInitiated[1] = true;
			currentFunction[1] = true;
			
		}else if(current.value.equals("Winner")){
			
			//Winner
			javaString += "public static Player[] Winner(Main game){\n";
			isInitiated[2] = true;
			currentFunction[2] = true;
			
		}else if(current.value.equals("InitializeCells")){
			
			//InitializeCells
			javaString += "public static void InitializeCells(Main game, int x, int y){\n";
			isInitiated[3] = true;
			currentFunction[3] = true;
			
		}else if(current.value.equals("CloseFunction")){
			
			//close function
			javaString += "}\n";
			for(int i = 0;i<currentFunction.length;i++){
				currentFunction[i] = false;
			}
			
		}
		
		//<--------Block-------------->
		
		else if(current.value.equals("block")){
			
			//block
			//push child in - 1 child
			stack.push(current.children.get(0));
			
		}
		
		//<------------Statement / Statement List ------>
		
		else if(current.value.equals("stmt_list")){
			
			//stmt_list
			if(current.children.get(0).value.equals("for")){
				
				stack.push(current.children.get(1)); // stmt_list
				stack.push(current.children.get(0)); // stmt
				
			}else if(current.children.get(0).value.equals("if")){
				
				stack.push(current.children.get(1)); // stmt_list
				stack.push(current.children.get(0)); // stmt
					
			}else if(current.children.get(0).value.equals("if-else")){
				
				stack.push(current.children.get(1)); // stmt_list
				stack.push(current.children.get(0)); // stmt
				
			}else if(current.children.get(0).value.equals("while")){
				
				stack.push(current.children.get(1)); // stmt_list
				stack.push(current.children.get(0)); // stmt
				
			}else{
				
				stack.push(current.children.get(1)); // stmt_list
				stack.push(new BGDLTreeNode("EndStatement"));
				stack.push(current.children.get(0)); // stmt
				
			}
			
		}else if(current.value.equals("empty")){
			
			//stmt_list is empty
			//do nothing
			
		}else if(current.value.equals("EndStatement")){
			
			//end of statement
			javaString += ";\n";
			
		}
		
		//<----------------For----------------------->
		
		else if(current.value.equals("for")){
			
			javaString += "for(";
			stack.push(new BGDLTreeNode("EndFor"));
			stack.push(current.children.get(3));
			stack.push(new BGDLTreeNode("StartForBlock"));
			stack.push(current.children.get(2));
			stack.push(new BGDLTreeNode("ForSemi"));
			stack.push(current.children.get(1));
			stack.push(new BGDLTreeNode("ForSemi"));
			stack.push(current.children.get(0));
			
		}else if(current.value.equals("ForSemi")){
			
			javaString += ";";
			
		}else if(current.value.equals("StartForBlock")){
			
			javaString += "){\n";
			
		}else if(current.value.equals("EndFor")){
			
			javaString += "}\n";
			
		}
		
		//<-------------If----------------------->
		else if(current.value.equals("if")){
			
			javaString += "if(";
			stack.push(new BGDLTreeNode("EndIf"));
			stack.push(current.children.get(1));
			stack.push(new BGDLTreeNode("MiddleIf"));
			stack.push(current.children.get(0));
			
		}else if(current.value.equals("MiddleIf")){
			javaString += "){\n";
		}else if(current.value.equals("EndIf")){
			javaString += "}\n";
		}else if(current.value.equals("if-else")){
			
			javaString += "if(";
			stack.push(current.children.get(2));
			stack.push(new BGDLTreeNode("EndIfElse"));
			stack.push(current.children.get(1));
			stack.push(new BGDLTreeNode("MiddleIf"));
			stack.push(current.children.get(0));
			
		}else if(current.value.equals("EndIfElse")){
			
			if(stack.peek().value.equals("if")
					||stack.peek().value.equals("if-else")){
				javaString += "}else ";
			}else{
				
				//else
				javaString += "}else{\n";
				BGDLTreeNode elseClause = stack.pop();
				stack.push(new BGDLTreeNode("EndIf"));
				stack.push(elseClause);
				
			}
			
			
		}
		
		//<---------------while------------------->
		
		else if(current.value.equals("while")){
			
			javaString += "while(";
			stack.push(new BGDLTreeNode("EndIf"));
			stack.push(current.children.get(1));
			stack.push(new BGDLTreeNode("MiddleIf"));
			stack.push(current.children.get(0));
			
		}
		
		//<------------- var_init ---------------->
		
		else if(current.value.equals("var_init")){
			
			javaString += current.children.get(0).value + " " + current.children.get(1).value;
			
		}
		
		//<------------- "=" operation ----------->
		
		else if(current.value.equals("=")){
			
			//distinguish which = it is - using left hand side
			if(current.children.get(0).value.equals("cell_expr")){
				//cell in InitializeCell
				//pop EndOfStatement out
				stack.pop();
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("CellInitializeCells"));
				stack.push(current.children.get(0));
				
			}else{
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("RightHandSide"));
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("RightHandSide")){
			
			javaString += " = ";
			
		}
		
		//<------------DOT Operation--------------->
		
		else if(current.value.equals(".")){
			
			//check if it's an array expression
			if(stack.peek().value.equals("Array Expression Right")){
				//pop dummy out
				stack.pop();
				//pop index out
				BGDLTreeNode index = stack.pop();
				stack.push(new BGDLTreeNode("EndDotOperation"));
				stack.push(index);
				stack.push(new BGDLTreeNode("Array Expression Right"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("MiddleDotOperation Right"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("StartDotOperation"));
				
			}else if(stack.peek().value.equals("RightHandSide")){
				stack.pop();
				stack.push(new BGDLTreeNode("EndDotOperation"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("MiddleDotOperation Right"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("StartDotOperation"));
			}else if(stack.peek().value.equals("Array Expression No Right")){
			
				//pop dummy out
				stack.pop();
				//pop index out
				BGDLTreeNode index = stack.pop();
				stack.push(new BGDLTreeNode("EndDotOperation"));
				stack.push(index);
				stack.push(new BGDLTreeNode("Array Expression"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("MiddleDotOperation"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("StartDotOperation"));
			
			}else{
				
				stack.push(new BGDLTreeNode("EndDotOperation"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("MiddleDotOperation"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("StartDotOperation"));
				
			}
			
			
		}else if(current.value.equals("StartDotOperation")){
		
			if(stack.peek().value.equals("Board")){
				stack.pop();
				javaString += "game.board.";
			}else if(stack.peek().value.equals("GameState")){
				stack.pop();
				javaString += "game.gameState.";
			}
			
		}else if(current.value.equals("MiddleDotOperation")){
			
			//for GET function
			current = stack.pop();
			
			if(current.value.equals("numPlayers")){
				
				javaString += "getNumPlayers(";
				
			}else if(current.value.equals("player")){
				
				//player[i].attribute
				javaString += "getPlayer()";
				if(stack.peek().value.equals("Array Expression")){
					//pop this dummy out
					stack.pop();
					javaString += "[";
					//pop index out... put end of array in... then put index in
					BGDLTreeNode indexNode = stack.pop();
					//need to pop EndOfDotOperation out too
					stack.pop();
					if(stack.peek().value.equals("MiddleDotOperation")){
						stack.push(new BGDLTreeNode("dot"));
					}
					stack.push(new BGDLTreeNode("EndOfArrayNew"));
					stack.push(indexNode);
				}
				
			}else if(current.value.equals("points")){
				
				javaString += "getPoints(";
				
			}else if(current.value.equals("activePlayer")){
				
				javaString += "getActivePlayer()";
				if(stack.peek().value.equals("Array Expression")){
					//pop this dummy out
					stack.pop();
					javaString += "[";
					//pop index out... put end of array in... then put index in
					BGDLTreeNode indexNode = stack.pop();
					//need to pop EndOfDotOperation out too
					stack.pop();
					stack.push(new BGDLTreeNode("EndOfArrayNew"));
					stack.push(indexNode);
				}
				
			}else if(current.value.equals("numRounds")){
				
				javaString += "getNumRounds(";
				
			}else if(current.value.equals("currentPlayer")){
				
				javaString += "getCurrentPlayer(";
				
			}else if(current.value.equals("numTurns")){
				
				javaString += "getNumTurns(";
				
			}else if(current.value.equals("name")){
				
				javaString += "getName(";
				
			}else if(current.value.equals("direction")){
				
				javaString += "getDirection(";
				
			}
			
		}else if(current.value.equals("MiddleDotOperation Right")){
			
			//for SET function
			current = stack.pop();
			//NOTE: The word in BGDL file is DIFFERENT from function's name in libraries
			if(current.value.equals("title")){
				
				if(!currentFunction[0]){
					//not in InitializeBoard
					return "Error: "+current.value+" is supposed to be in InitializeBoard only";
				}
				
				javaString += "setTitle(";
				// for this function, it need right hand side to put value in between
				//push child to indicate this
				stack.push(new BGDLTreeNode("NeedValue"));
				
			}else if(current.value.equals("width")){
				
				if(!currentFunction[0]){
					//not in InitializeBoard
					return "Error: "+current.value+" is supposed to be in InitializeBoard only";
				}
				
				javaString += "setWidth(";
				//need value
				stack.push(new BGDLTreeNode("NeedValue"));
				
			}else if(current.value.equals("height")){
				
				if(!currentFunction[0]){
					//not in InitializeBoard
					return "Error: "+current.value+" is supposed to be in InitializeBoard only";
				}
				
				javaString += "setHeight(";
				//need value
				stack.push(new BGDLTreeNode("NeedValue"));
				
			}else if(current.value.equals("player")){
				
				if(!currentFunction[0]){
					//not in InitializeBoard
					return "Error: "+current.value+" is supposed to be in InitializeBoard only";
				}
				
				//need to peek if it's Board.player = new... or Board.player[...] = new ...
				if(stack.peek().value.equals("Array Expression Right")){
					//Board.player[...] = new ...
					javaString += "setPlayerProperties(";
					//change order in stack to be.. "index" on top of "Array Expression"
					stack.pop();
					current = stack.pop();
					stack.push(new BGDLTreeNode("NeedValue"));
					stack.push(new BGDLTreeNode("Array Expression"));
					stack.push(current);
					
				}else{
					
					//Board.player = new...
					javaString += "setPlayer(";
					stack.push(new BGDLTreeNode("NeedValue"));
				}
				
				
			}else if(current.value.equals("dice")){
				
				if(!currentFunction[0]){
					//not in InitializeBoard
					return "Error: "+current.value+" is supposed to be in InitializeBoard only";
				}
				
				//need to peek if it's Board.dice = new... or Board.dice[...] = new ...
				if(stack.peek().value.equals("Array Expression Right")){
					//Board.dice[...] = new ...
					javaString += "setDiceSides(";
					//change order in stack to be.. "index" on top of "Array Expression"
					stack.pop();
					current = stack.pop();
					stack.push(new BGDLTreeNode("NeedValue"));
					stack.push(new BGDLTreeNode("Array Expression"));
					stack.push(current);
					
				}else{
					//Board.player = new...
					javaString += "setDice(";
					stack.push(new BGDLTreeNode("NeedValue"));
				}
				
			}else{
				
				System.out.println("Error Translation - Not found: "+current.value);
				
			}
			
		}else if(current.value.equals("EndDotOperation")){
			
			//end of dot operation
			javaString += ")";
			
		}else if(current.value.equals("NeedValue")){
			
			//get value after EndDotOperation and then push EndDotOperation back
			//value always 2 next pop
			stack.pop(); // get EndDotOperation out
			current = stack.pop(); // get the value
			stack.push(new BGDLTreeNode("EndDotOperation"));
			stack.push(current);
			
		}
		
		//<------------------Return----------------->
		
		else if(current.value.equals("return")){
			javaString += "return ";
			stack.push(current.children.get(0));
		}
		
		//<---------------Array_Init--------------->>
		
		else if(current.value.equals("array_init")){
			
			//initiate array
			javaString += ""+current.children.get(0).value+"[] "+current.children.get(1).value;
			
		}
		
		//<---------------Array_new---------------->>
		
		else if(current.value.equals("array_new")){
			
			//grammar >> new CHILD_1[CHILD_2];
			
			javaString += "new "+current.children.get(0).value+"[";
			//put end of new Array in stack
			stack.push(new BGDLTreeNode("EndOfArrayNew"));
			stack.push(current.children.get(1));
			
		}else if(current.value.equals("EndOfArrayNew")){
			
			javaString += "]";
			
		}
		
		//<----------------array_expr - expr LBRACK expr RBRACK ----->
		
		else if(current.value.equals("array_expr")){
			
			if(stack.peek().value.equals("RightHandSide")){
				
				stack.pop();
				stack.push(current.children.get(1)); // index
				stack.push(new BGDLTreeNode("Array Expression Right"));
				stack.push(current.children.get(0)); // expression
				
			}else{
				
				stack.push(current.children.get(1)); // index
				stack.push(new BGDLTreeNode("Array Expression No Right"));
				stack.push(current.children.get(0)); // expression
				
			}

			
		}else if(current.value.equals("Array Expression")){
			
			javaString += ", ";
			
			
		}else if(current.value.equals("Array Expression Right")){
			
			javaString += "[";
			//pop index out
			BGDLTreeNode index = stack.pop();
			stack.push(new BGDLTreeNode("RightHandSide"));
			stack.push(new BGDLTreeNode("EndArrayExpression"));
			stack.push(index);
			
		}else if(current.value.equals("EndArrayExpression")){
			
			javaString += "]";
			
		}
		
		//<--------------complexType_new: NEW complexType LPAREN expr_list RPAREN----->
		
		else if(current.value.equals("new")){
			
			//can ignore the type in first child because type has been already identified before this
			stack.push(current.children.get(1));
			
		}
		
		//<---------------expr_list: expr COMMA expr_list------->
		
		else if(current.value.equals("expr_list")){
			
			stack.push(current.children.get(1));
			stack.push(new BGDLTreeNode("Comma"));
			stack.push(current.children.get(0));
			
		}
		
		//<----------------COMMA------------------>
		
		else if(current.value.equals("Comma")){
			
			javaString += ", ";
			
		}
		
		//<------------------LITERAL DOT------------>
		
		else if(current.value.equals("dot")){
			
			javaString += ".";
			
		}
		
		//<-------------Cell--------------------->
		else if(current.value.equals("cell_expr")){
			
			if(stack.peek().value.equals("CellInitializeCells")){
				
				if(!currentFunction[3]){
					//not in InitializeCells
					return "Error: "+current.value+" is supposed to be in InitializeCells only";
				}
				
				//Cell in InitializeCells
				stack.pop();//pop dummy out
				if(isFirstCell){
					javaString += "if((x==";
					isFirstCell = false;

				}else{
					javaString += "else if((x==";
				}
				
				stack.push(new BGDLTreeNode("CellCondition"));
				stack.push(new BGDLTreeNode("EndCell"));
				stack.push(current.children.get(2));
				stack.push(new BGDLTreeNode("MiddleCell"));
				stack.push(current.children.get(1));
				
			}else{
				stack.push(current.children.get(2));
				stack.push(new BGDLTreeNode("Comma"));
				stack.push(current.children.get(1));
			}
			
		}else if(current.value.equals("MiddleCell")){
			
			javaString += ")&&(y==";
			
		}else if(current.value.equals("EndCell")){
			
			javaString += ")){\n";
			
		}else if(current.value.equals("CellCondition")){
			
			//pop the condition out
			BGDLTreeNode condition = stack.pop();
			stack.push(new BGDLTreeNode("EndIf"));
			stack.push(condition);
			
		}
		
		//<-----------------Parenthesis-------------->
		
		else if(current.value.equals("CloseParenthesis")){
			
			javaString += ")";
			
		}else if(current.value.equals("OpenParenthesis")){
			
			javaString += "(";
			
		}
		
		//<----------------binary_expr------------->
		
		else if(current.value.equals("||")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_||"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("&&")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_&&"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("<")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_<"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals(">")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_>"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}			
		}else if(current.value.equals("==")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_=="));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}			
		}else if(current.value.equals("!=")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_!="));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}			
		}else if(current.value.equals("<=")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_<="));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}			
			
		}else if(current.value.equals(">=")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_>="));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("+")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_+"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("-")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_-"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("*")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_*"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("/")){
			
			if(isBooleanOperation(current.children.get(1))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(1));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(1));
			}
			stack.push(new BGDLTreeNode("LITERAL_/"));
			if(isBooleanOperation(current.children.get(0))){
				stack.push(new BGDLTreeNode("CloseParenthesis"));
				stack.push(current.children.get(0));
				stack.push(new BGDLTreeNode("OpenParenthesis"));
			}else{
				stack.push(current.children.get(0));
			}
			
		}else if(current.value.equals("LITERAL_||")){
			
			javaString += "||";
			
		}else if(current.value.equals("LITERAL_&&")){
			
			javaString += "&&";
			
		}else if(current.value.equals("LITERAL_<")){
			
			javaString += "<";
			
		}else if(current.value.equals("LITERAL_>")){
			
			javaString += ">";
			
		}else if(current.value.equals("LITERAL_==")){
			
			javaString += "==";
			
		}else if(current.value.equals("LITERAL_!=")){
			
			javaString += "!=";
			
		}else if(current.value.equals("LITERAL_<=")){
			
			javaString += "<=";
			
		}else if(current.value.equals("LITERAL_>=")){
			
			javaString += ">=";
			
		}else if(current.value.equals("LITERAL_+")){
			
			javaString += "+";
			
		}else if(current.value.equals("LITERAL_-")){
			
			javaString += "-";
			
		}else if(current.value.equals("LITERAL_*")){
			
			javaString += "*";
			
		}else if(current.value.equals("LITERAL_/")){
			
			javaString += "/";
			
		}
		
		//<---------------unary_expr----------------->
		
		else if(current.value.equals("++")){
			
			stack.push(new BGDLTreeNode("LITERAL_++"));
			stack.push(current.children.get(0));
			
		}else if(current.value.equals("--")){
			
			stack.push(new BGDLTreeNode("LITERAL_--"));
			stack.push(current.children.get(0));
			
		}else if(current.value.equals("!")){
			
			javaString += "!";
			stack.push(current.children.get(0));
			
		}else if(current.value.equals("unary -")){
			
			javaString += "-";
			stack.push(current.children.get(0));
			
		}else if(current.value.equals("LITERAL_++")){
			
			javaString += "++";
			
		}else if(current.value.equals("LITERAL_--")){
			
			javaString += "--";
			
		}
		
		//<----------------LITERALS----------------->>
		
		else if(current.value.equals("STRING_LITERAL")){
			
			javaString += current.children.get(0).value;
			
		}else if(current.value.equals("INT_LITERAL")){
			
			javaString += current.children.get(0).value;
			
		}else if(current.value.equals("BOOLEAN_LITERAL")){
			
			javaString += current.children.get(0).value;
			
		}else if(current.value.equals("DOUBLE_LITERAL")){
			
			javaString += current.children.get(0).value;
			
		}
		
		//<------------Action in Cell Initialize------>
		
		else if(current.value.equals("action")){
			
			if(!currentFunction[3]){
				//not in InitializeCells
				return "Error: "+current.value+" is upposed to be in InitializeCells";
			}
			
			javaString += "game."+current.children.get(0).value+"(";
			stack.push(new BGDLTreeNode("CloseParenthesis"));
			stack.push(current.children.get(1));
			
		}
		
		//<-------------Identifier------->
		
		else{
			
			javaString += current.value;
			
		}
		
		return "";
		
	}

	private boolean isBooleanOperation(BGDLTreeNode current){
		
		//check if it is boolean operation
		if(current.value.equals("||")
				||current.value.equals("&&")
				||current.value.equals("<")
				||current.value.equals(">")
				||current.value.equals("==")
				||current.value.equals("!=")
				||current.value.equals("<=")
				||current.value.equals(">=")
				||current.value.equals("+")
				||current.value.equals("-")
				||current.value.equals("*")
				||current.value.equals("/")){
			
			//add parenthesis
			return true;
			
		}
		
		return false;
		
	}
	
	private void writeOutput() {
		
		 try {
			Writer output = new BufferedWriter(new FileWriter(new File("BoardGame.java")));
			//write output
			output.write(javaString);
			output.close();
		} catch (IOException e) {
			System.out.println("I/O Exception");
			return;
		}
		
	}
	
}
